package com.dhq.myapp.base.divider

import android.annotation.SuppressLint
import android.graphics.Canvas
import android.graphics.Rect
import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.view.View
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.LinearLayoutManager.HORIZONTAL
import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL

/**
 * DESC RecyclerViewDivider工具类
 * Created by admin on 2017/11/17.
 */
class LinearDivider(builder: Builder) : DividerFactory() {

    private val bounds = Rect()
    private val divider: Drawable?
    private val strokeWidth: Int
    private val strokeHeight: Int
    private val hideLastDivider: Boolean
    private var orientation = VERTICAL
    private var lastPosition = -1

    init {
        this.divider = builder.drawable
        this.strokeWidth = builder.columnSpace
        this.strokeHeight = builder.rowSpace
        this.hideLastDivider = builder.hideLastDivider
    }

    @SuppressLint("WrongConstant")
    override fun drawDivider(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        if (parent.layoutManager == null || divider == null) {
            return
        }
        val layoutManager = parent.layoutManager

        // 判断是否是LinearLayoutManager
        if (layoutManager is LinearLayoutManager) {
            orientation = layoutManager.orientation
            if (orientation == HORIZONTAL) {
                drawHorizontal(c, parent)
            } else {
                drawVertical(c, parent)
            }
        }
    }

    @SuppressLint("WrongConstant")
    override fun calculateItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
        val layoutManager = parent.layoutManager as? LinearLayoutManager ?: return
        orientation = layoutManager.orientation
        lastPosition = parent.adapter?.itemCount?.minus(1) ?: -1
        val position = getAdapterPosition(view)

        if (divider == null) {
            outRect.set(0, 0, 0, 0)
            return
        }

        if (orientation == HORIZONTAL) {
            outRect.set(0, 0, getIntrinsicWidth(position), 0)
        } else {
            outRect.set(0, 0, 0, getIntrinsicHeight(position))
        }
    }

    private fun drawVertical(canvas: Canvas, parent: RecyclerView) {
        canvas.save()
        var left: Int
        var right: Int

        val childCount = if (hideLastDivider) parent.childCount - 1 else parent.childCount
        for (i in 0 until childCount) {
            val child = parent.getChildAt(i)
            val position = getAdapterPosition(child)
            left = parent.paddingLeft
            right = parent.width - parent.paddingRight

            parent.getDecoratedBoundsWithMargins(child, bounds)
            val bottom = bounds.bottom + Math.round(child.translationY)
            val top = bottom - getIntrinsicHeight(position)

            val drawable = getDivider() ?: continue
            drawable.setBounds(left, top, right, bottom)
            drawable.draw(canvas)
        }
        canvas.restore()
    }

    private fun drawHorizontal(canvas: Canvas, parent: RecyclerView) {
        canvas.save()
        var top: Int
        var bottom: Int

        val childCount = if (hideLastDivider) parent.childCount - 1 else parent.childCount
        for (i in 0 until childCount) {
            val child = parent.getChildAt(i)
            val position = getAdapterPosition(child)

            top = parent.paddingTop
            bottom = parent.height - parent.paddingBottom
            canvas.clipRect(
                parent.paddingLeft, top, parent.width - parent.paddingRight,
                bottom
            )

            parent.layoutManager?.getDecoratedBoundsWithMargins(child, bounds)
            val right = bounds.right + Math.round(child.translationX)
            val left = right - getIntrinsicWidth(position)
            val drawable = getDivider() ?: continue
            drawable.setBounds(left, top, right, bottom)
            drawable.draw(canvas)
        }
        canvas.restore()
    }

    private fun getAdapterPosition(view: View): Int {
        return (view.layoutParams as RecyclerView.LayoutParams).viewAdapterPosition
    }

    private fun getDivider(): Drawable? {
        return divider
    }

    private fun getIntrinsicHeight(position: Int): Int {
        if (hideLastDivider && position == lastPosition) {
            return 0
        }
        return if (divider is ColorDrawable) {
            strokeHeight
        } else {
            divider?.intrinsicHeight ?: 0
        }
    }

    private fun getIntrinsicWidth(position: Int): Int {
        if (hideLastDivider && position == lastPosition) {
            return 0
        }
        return if (divider is ColorDrawable) {
            strokeWidth
        } else {
            divider?.intrinsicWidth ?: 0
        }
    }
}